<!DOCTYPE html>
<html lang="en" style="">
<head>
	<title>1.4-API-Request | PhalApi - A light-weight PHP framework for API</title>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<link rel="icon" href="http://webtools.qiniudn.com/dog_catch.png" type="image/x-icon" />
	<meta name="description" content="PhalApiis A light-weight PHP framework for API!">
	<meta name="keywords" content="PhalApi,phalapi,phalapi API develop,backend framework,restful,web services,saas,microservice,API framework,open API framework,PHP API framework,php web framework">
	<meta name="author" content="dogstar">

	<link rel="stylesheet" type="text/css" href="./../..//css/screen.css?20150211" />
</head>

<body>
<a href="https://github.com/phalapi/phalapi">
	<img alt="Fork me on GitHub" data-canonical-src="http://7xslqv.com1.z0.glb.clouddn.com/images/2/2d/9e69c0ebaff22a24e241a0244532e.png" src="http://7xslqv.com1.z0.glb.clouddn.com/images/2/2d/9e69c0ebaff22a24e241a0244532e.png" style="position: absolute; top: 0; right: 0; border: 0;">
</a>

<!-- 最顶部的语言(S) -->
<div class="grid-wrapper navbar desktop-only">
	<div class="grid">
		<div class="grid__cell">
			<ul id="language-switchers" class="navbar__links navbar--left">
                <li class="menu-item"><a title="PhalApi官方网站中文版" href="/" class="menu-item__link">Chinese</a></li>
				<li class="menu-item"><a title="English version of PhalApi website" href="/wikis/en/" class="menu-item__link">English</a></li>
			</ul>
			<ul id="util-menu" class="navbar__links navbar--right navbar--vertical-separator">
				<li class="menu-item"><a href="#" class="menu-item__link contact-us-spec">Welcome Here!</a></li>
			</ul>
		</div>
	</div>
</div>
<!-- 最顶部的语言(E) -->

<!-- 顶部导航菜单(S) -->
<div class="grid-wrapper desktop-only">
	<div class="grid">
		<div class="grid__cell">
			<div class="header__header-wrapper">
				<a title="PhalApi" href="http://www.phalapi.net" class="header__logo"><img src="http://webtools.qiniudn.com/master-LOGO-20150410_33.jpg" id="tw-logo" alt="PhalApi"></a>
				<ul id="main-menu" class="header__menu">
					<li class="menu-item"><a href="http://qa.phalapi.net/" class="menu-item__link insights-spec" target="_blank">Community</a></li>
					<li class="menu-item"><a href="https://github.com/phalapi/phalapi" class="menu-item__link insights-spec" target="_blank">Download</a></li>
					<li class="menu-item"><a href="/wikis/en/" class="menu-item__link events-spec" target="_blank">Wikis</a></li>
    				<li class="menu-item"><a href="/docs_en/" class="menu-item__link events-spec" target="_blank">Classes docs</a></li>
					<li class="menu-item"><a href="http://demo.phalapi.net/" class="menu-item__link products-spec" target="_blank">Demo</a></li>
					<li class="menu-item"><a href="/about.html" class="menu-item__link about-us-spec" target="_blank">About us</a></li>
				</ul>
			</div>
		</div>
	</div>
</div>
<!-- 顶部导航菜单(E) -->


    <div class="grid-wrapper">
        <div class="grid">
            <div class="grid__cell">
                <h2>1.4 API Request</h2>
<h3>1.4.1 Specify service: ?service=XXX.XXX</h3>
<p>Client can request an API by specifing service, usually with service parameter by GET method. The form of URI to request is something like this.  </p>
<pre><code>API HOST + ENTRANCE + ?service=XXX.XXX  

e.g:  
http://dev.phalapi.com   +   /demo/  +  ?service=User.GetBaseInfo</code></pre>
<p>After we request with GET method in a browser, we can see some nginx logs which looks like:  </p>
<pre><code>127.0.0.1 - - [07/Feb/2015:22:46:46 -0800] "GET /demo/?service=User.GetBaseInfo&amp;sign=&amp;user_id=1 HTTP/1.1" 200 107 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:11.0) Gecko/20100101 Firefox/11.0"</code></pre>
<p>If we request by POST instead, we will see:  </p>
<pre><code>127.0.0.1 - - [07/Feb/2015:19:32:05 -0800] "POST /demo/?service=User.GetBaseInfo&amp;sign= HTTP/1.1" 200 135 "-" "-"</code></pre>
<p>The first letter of service parameter is case-insensitive, but we encourage it should be a capital letter. The API we request in above is related to Api_User::getBaseInfo.  </p>
<pre><code>class Api_User extends PhalApi_Api {

    public function getBaseInfo() {
    }
}</code></pre>
<p>If there is no <code>service</code> parameter, it will be <code>Default.Index</code> in default.  </p>
<h3>1.4.2 When to use GET params?</h3>
<p>When developing a project, we will run into some common API params, such as client agent, the version ofclient app, app key, etc. These params should be post by GET method, because we can statistics, analyse and locate where the bugs are by access.log in nginx in the future.  That is one of best practices.  </p>
<h3>1.4.3 When to use POST params?</h3>
<p>On the otherhand, we suggest to use POST params while we in the situations as beblow.  </p>
<ul>
<li>
<ol>
<li>sensitive data, such as password.  </li>
</ol>
</li>
<li>
<ol>
<li>some special characters or big data package.  </li>
</ol>
</li>
</ul>
<h3>1.4.4 How to get header information?</h3>
<p>There are some headers in each request, and we can get header information as below.  </p>
<p>Assume the request header is:  </p>
<pre><code>Host        demo.phalapi.net
User-Agent  Mozilla/5.0</code></pre>
<p>If we want to just get one header, e.g. host in this case, we can:  </p>
<pre><code>$host = DI()-&gt;request-&gt;getHeader("Host"); // we will get "demo.phalapi.net"</code></pre>
<p>If we want to get all the headers, we can:  </p>
<pre><code>$headers = DI()-&gt;request-&gt;getAllHeaders(); // which will return an array</code></pre>
<h3>1.4.5 Switch to other param source</h3>
<p>As we can see before, we could request an API by GET method, or POST method, or both of them, which will retrieve client params from <code>$_GET</code>, <code>$_POST</code>, and <code>$_REQUEST</code>. But in some situations, we need to use other param source. In this case, we can register <code>DI()-&gt;request</code> with specified data source in the file <code>index.php</code>.  </p>
<p>For example, when force to use POST data, these code should be added into <code>index.php</code>.  </p>
<pre><code>//vim ./index.php

$HTTP_RAW_POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : "{}";
DI()-&gt;request = new PhalApi_Request(array_merge($_GET,json_decode($HTTP_RAW_POST_DATA, true))); </code></pre>
<p>While running in unit tests, we need to mock data for API to be tested.  </p>
<pre><code>// mock data
$data = array(...);

DI()-&gt;request = new PhalApi_Request($data);</code></pre>
<p>We can also mock data with PhalApi_Helper_TestRunner class.  </p>
<pre><code>    public function testIndexByRunner()
    {
        //Step 1. build a URL
        $url = 'service=Default.Index&amp;username=dogstar';
        $params = array();

        //Step 2. excute request  
        $rs = PhalApi_Helper_TestRunner::go($url, $params);
    }</code></pre>
<h3>1.4.6 Encrypt requst params</h3>
<p>It's a good idea to encrypt some sensitive client params for security in our project. In that way, we need to override <code>PhalApi_Request::genData()</code>.  </p>
<p>Assume our project want to post all the client params in <code>$_POST['data']</code> after base64 encoding.  </p>
<p>Firstly, create an new request class and implement how to decode client data.  </p>
<pre><code>&lt;?php

class Common_Request extends PhalApi_Request {

    public function genData($data) {
        if (!isset($data) || !is_array($data)) {
            $data = $_POST; // only recieve POST data
        }

        return isset($data['data']) ? base64_decode($data['data']) : array();
    }
}</code></pre>
<p>Secondly, register <code>DI()-&gt;request</code> in file <code>index.php</code>.  </p>
<pre><code>DI()-&gt;request = 'Common_Request';</code></pre>
<p>So it is! Try it out, and how to encrypt client data is up to you.  </p>
<h3>1.4.7 API signature with filter</h3>
<p>In PhalApi, we treat many resource as back-end service. The filter servcie, which is <code>DI()-&gt;filter</code>, can do some extral operations before excute a request. Usually, we can check API signature in the filter.  </p>
<p>There is a default filter service, i.e.  <code>PhalApi_Filter_SimpleMD5</code> class. You can open it by uncommenting the code below in file <code>init.php</code>.  </p>
<pre><code>// filter service
DI()-&gt;filter = 'PhalApi_Filter_SimpleMD5';</code></pre>
<p>Then client have to generate a sign as below.  </p>
<ul>
<li>
<ol>
<li>exclude sign param(default to be sign)  </li>
</ol>
</li>
<li>
<ol>
<li>sort all the rest of params  </li>
</ol>
</li>
<li>
<ol>
<li>concatenate all the value of params as string after sort  </li>
</ol>
</li>
<li>
<ol>
<li>md5  </li>
</ol>
</li>
</ul>
<p>For example, we will request such a URI: <code>?service=Default.Index&amp;username=dogstar</code>.  </p>
<ol>
<li>
<p>exclude sign param(default to be sign)
?service=Default.Index&amp;username=dogstar  </p>
</li>
<li>
<p>sort all the rest of params<br />
service=Default.Index<br />
username=dogstar  </p>
</li>
<li>
<p>concatenate all the value of params as string after sort<br />
&quot;Default.Indexdogstar&quot; = &quot;Default.Index&quot; + &quot;dogstar&quot;  </p>
</li>
<li>md5<br />
sign = 35321cc43cfc1e4008bf6f1bf9b7e3b8 = md5(&quot;Default.Indexdogstar&quot;)  </li>
</ol>
<p>At last, client need to add sign into GET params. Finally, the URI should be: <code>?service=Default.Index&amp;username=dogstar&amp;sign=35321cc43cfc1e4008bf6f1bf9b7e3b8</code>.  </p>
<h4>Check it out!</h4>
<p>Firstly, let's request without sign. Of course, it'll fail.  </p>
<pre><code>http://localhost/phalapi/public/demo/?service=Default.Index&amp;username=dogstar

Reponse:
{
    "ret": 406,
    "data": [],
    "msg": "illegal request: wrong sign"
}</code></pre>
<p>When fail to check the sign, we can get the right sign in logs.  </p>
<pre><code>2015-10-23 23:16:16|DEBUG|Wrong Sign|{"needSign":"35321cc43cfc1e4008bf6f1bf9b7e3b8"}</code></pre>
<p>Secondly, let's request with a right sign, we generate in above.  </p>
<pre><code>http://localhost/phalapi/public/demo/?service=Default.Index&amp;username=dogstar&amp;sign=35321cc43cfc1e4008bf6f1bf9b7e3b8</code></pre>
<p>And it works!  </p>
<p>If we want to rename the name of sign parameter, we can set the new name when registering <code>DI()-&gt;filter</code>. For example, we use <code>s</code> for short instead.  </p>
<pre><code>DI()-&gt;filter = new PhalApi_Filter_SimpleMD5('s');</code></pre>
<h4>How to cancel signature verification in some APIs?</h4>
<p>We can cancel signature verification by overriding <code>PhalApi_Api::filterCheck()</code> function in our implementation API sub-class. And do nothing inside <code>filterCheck()</code>.  </p>
<pre><code>//vim ./Demo/Api/Default.php 
class Api_Default extends PhalApi_Api
{
    //....

    protected function filterCheck()
    {
    }
}</code></pre>
<h3>1.4.8 COOKIE</h3>
<p><code>DI()-&gt;cookie</code> is not a default backend service, which means we need to register it in file <code>init.php</code> when we want to deal with COOKIEs.  </p>
<p>It's very simple to register <code>DI()-&gt;cookie</code> as other backend services.  </p>
<pre><code>// COOKIE
DI()-&gt;cookie = 'PhalApi_Cookie';</code></pre>
<p>There are three main operations in <code>PhalApi_Cookie</code>, and they are <code>set</code>, <code>get</code>, and <code>delete</code>.  </p>
<pre><code>// set a COOKIE
DI()-&gt;cookie-&gt;set('name', 'phalapi', $_SERVER['REQUEST_TIME'] + 600);

// get a COOKIE
echo DI()-&gt;cookie-&gt;get('name');  //输出 phalapi

// delete a COOKIE
DI()-&gt;cookie-&gt;delete('name');</code></pre>
<h4>Smart COOKIE in PhalApi</h4>
<p>In fact, it's more complicated to use COOKIE in the real world. According defferent situations, we might need to encrypt COOKIE, or get  the cookie after we set in the same request. All these situations can be under control with out smart COOKIE service, i.e. <code>PhalApi_Cookie_Multi</code> class.  </p>
<p>Again, if we want a smart COOKIE service, we need to register it with some config.  </p>
<pre><code>$config = array('crypt' =&gt; $crypt, 'key' =&gt; 'a secrect');
DI()-&gt;cookie = new PhalApi_Cookie_Multi($config);</code></pre>
<p>We config how to encrypt COOKIE here. <code>crypt</code> will encrypt the COOKIE, and default is <code>DI()-&gt;crypt</code>, which need to implement interface <code>PhalApi_Crypt</code>. <code>key</code> is the encryption key.  </p>
<p>In order to show how to encrypt our COOKIE with <code>PhalApi_Cookie_Multi</code>, let's take an example step by step.  </p>
<p>First of all, create an encryption class, which implement interface <code>PhalApi_Crypt</code>. It is really simple, just doing <code>base64_encode</code> and <code> base64_decode</code>.  </p>
<pre><code>class Cookie_Crypt_Mock implements PhalApi_Crypt {

    public function encrypt($data, $key) {
        return base64_encode($data);
    }

    public function decrypt($data, $key) {
        return base64_decode($data);
    }
}</code></pre>
<p>Then register <code>DI()-&gt;cookie</code> with Cookie_Crypt_Mock in <code>init.php</code>.  </p>
<pre><code>$config = array('crypt' =&gt; new Cookie_Crypt_Mock(), 'key' =&gt; 'a secrect');
DI()-&gt;cookie = new PhalApi_Cookie_Multi($config);</code></pre>
<p>Now we can test whether it works correctly. Let's create an new API service as below.    </p>
<pre><code>    public function cookieTest() {
        $rs = array();

        $rs['aEKey'] = DI()-&gt;cookie-&gt;get('name');
        DI()-&gt;cookie-&gt;set('name', 'phalapi', $_SERVER['REQUEST_TIME'] + 600);

        return $rs;

    }</code></pre>
<p>After request the API service, we can check the cookies in response.<br />
<img src="http://webtools.qiniudn.com/20150411204629.jpg" alt="" />  </p>
<p>AHA~! It works!  </p>
<h4>Some advise as other framwork will provide too</h4>
<ul>
<li>
<ol>
<li>DO NOT save sensitive data into COOKIE, protect your data  </li>
</ol>
</li>
<li>
<ol>
<li>DO NOT save too much data into COOKIE, just keep client fit  </li>
</ol>
</li>
</ul>
            </div>
        </div>
    </div>
    
 <!-- 广告位 -->
<!--
<div class="grid-wrapper desktop-only">
	<p align="center">
		<a href="http://7qnay5.com1.z0.glb.clouddn.com/走向开源的第一年%20-%20PhalApi%202015年度开源总结%20-%20官方出品%20-%2020151214.pdf" target="blank"><img width="950" height="100" src="http://7qnay5.com1.z0.glb.clouddn.com/PhalApi20151213-2.jpg"></a>
		<a href="http://qa.phalapi.net" target="blank"><img width="950" height="100" src="http://7qnay5.com1.z0.glb.clouddn.com/qa_ad_20150615.jpg"></a>
	</p>
</div>
-->

<!-- footer(S) -->
<div class="grid-wrapper footer">
	<div id="footer" class="grid">	

		<div class="grid__cell unit-1-2--lap">
			<h3><img src="http://webtools.qiniudn.com/master-LOGO-20150410_50.jpg" height="50"></h3>
            <p>
            <font size="3px;">PhalApi is a light-weight PHP framework for API.<br/>
                We try to keep PhalApi as stuip simple as possible!
            </font>
			</p>
			<p align="left">
				<font size="2px">&copy;2015-2016 PhalApi All Rights Reserved. 粤ICP备15028808号</font>
				<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1255326144'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s4.cnzz.com/z_stat.php%3Fid%3D1255326144%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"));</script>
			</p>
		</div>	

		<div class="grid__cell unit-1-2--lap">
			<h3>Thanks!</h3>

			<div class="nav">
				<ul class="footer__nav">
					<li class="menu-item"><a href="http://www.oschina.net/" class="menu-item__link" target="_blank">Open Source China</a></li>
					<li class="menu-item"><a href="http://www.phalconphp.com/en/" class="menu-item__link" target="_blank">Phalcon</a></li>
					<li class="menu-item"><a href="https://phpunit.de/manual/3.7/zh_cn/automating-tests.html" class="menu-item__link" target="_blank">PHPUnit</a></li>
					<li class="menu-item"><a href="http://www.thoughtworks.com/cn/" class="menu-item__link" target="_blank">ThoughtWorks</a></li>
				</ul>
			</div>

            <div id="perspectives">
                <div class="email-signup">
                    <strong><a href="https://auth.alipay.com/login/index.htm" target="_blank">Alipay&nbsp;</a>Donate: </strong>chanzonghuang@gmail.com
                </div>
            </div>

			<p>
				<!-- JiaThis Button BEGIN -->
				<div id="ckepop">
				<span class="jiathis_txt">Share: </span>
				<a class="jiathis_button_tsina">Weibo</a>
				<a href="http://www.jiathis.com/share" class="jiathis jiathis_txt jiathis_separator jtico jtico_jiathis" target="_blank">More</a>
				<a class="jiathis_counter_style"></a>
				</div>
				<script type="text/javascript" src="http://v2.jiathis.com/code/jia.js" charset="utf-8"></script>
				<!-- JiaThis Button END -->
				
			</p>
		</div>
	</div>
</div>
<!-- footer(E) -->

</body>

<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1254743218'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "w.cnzz.com/q_stat.php%3Fid%3D1254743218' type='text/javascript'%3E%3C/script%3E"));</script>

</html>
